﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Data;
using JXT.PrimaryKey.Batman.Reflection;
using JXT.PrimaryKey.Batman.Domain.Models;

namespace JXT.PrimaryKey.Batman.Domain.Repositories.MySql.Expressions
{
    public class InsertQuery : ISqlQuery {
        protected StringBuilder sb = new StringBuilder();
        protected IList<IDataParameter> parameterList = new List<IDataParameter>();

        private string getTableName(Type type)
        {
            return type.Name.ToLower();
        }

        #region ISqlQuery Members

        public string QueryText {
            get { return sb.ToString(); }
        }

        public System.Data.IDataParameter[] Parameters {
            get { return parameterList.ToArray(); }
        }

        #endregion

        public void Append<TEntity>(TEntity entity){
            if (entity == null)
                throw new ArgumentNullException("entity");
            string tableName = getTableName(entity.GetType());
            sb.AppendFormat("insert into {0}{1}{2}(",
                DbEnviroumentFactory.Instanse.LeftTag,
                tableName,
                DbEnviroumentFactory.Instanse.RightTag);
            StringBuilder values = new StringBuilder(" values(");
            var dics = entity.GetType().GetMetadataCacheDictionary();
            int defaultLen = values.Length;
            foreach (var item in dics) {
                if (item.Value.Property.Property.PropertyType.IsEntityOrValueObjectType()
                    || item.Value.Property.Property.PropertyType.IsInterface)
                    continue;
                string columnName = item.Value.Property.Name.ToLower();
                if (!item.Key.Equals("id", StringComparison.InvariantCultureIgnoreCase)) {
                    sb.AppendFormat("{0}{1}{2}, ",
                        DbEnviroumentFactory.Instanse.LeftTag,
                        columnName,
                        DbEnviroumentFactory.Instanse.RightTag);
                    values.AppendFormat("{0}{1}, ",
                        DbEnviroumentFactory.Instanse.ParameterChar,
                        columnName);
                    var value = item.Value.Property.Get(entity);
                    var valueType = value.GetType();
                    if (valueType.IsEnum)
                    {
                        value = Convert.ChangeType(value, valueType.GetEnumUnderlyingType());
                    }
                    parameterList.Add(ParameterFactory.Create(
                            String.Format("{0}{1}",
                                DbEnviroumentFactory.Instanse.ParameterChar,
                                columnName),
                                value));
                }
            }
            if (values.Length > defaultLen) {
                values.Remove(values.Length - 2, 2);
                values.Append(")");
                sb.Remove(sb.Length - 2, 2);
                sb.Append(")");
            }
            sb.Append(values.ToString());
            sb.Append(";");
            sb.Append(" select ");
            sb.Append(DbEnviroumentFactory.Instanse.NewRowIdFunction);
            sb.Append(";");
        }
    }
}
